package blackstar.plugin.monitor.reporter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author Ray (ayufox@gmail.com)
 */
public class MergeResultReporter implements ResultReporter
{
	public enum MergeStratege
	{
		MIN, MAX, AVARAGE
	}

	private int mergeCount = 5;

	private MergeStratege stratege = MergeStratege.AVARAGE;

	private ResultReporter targetReporter;

	private List<Long> datas = new ArrayList<Long>();

	public MergeResultReporter(ResultReporter targetReporter)
	{
		this.targetReporter = targetReporter;
	}

	public MergeResultReporter(ResultReporter targetReporter, int mergeCount)
	{
		this.targetReporter = targetReporter;
		this.mergeCount = mergeCount;
	}

	public MergeResultReporter(ResultReporter targetReporter,
			MergeStratege strategy)
	{
		this.targetReporter = targetReporter;
		if (strategy != null)
		{
			this.stratege = strategy;
		}
	}

	public MergeResultReporter(ResultReporter targetReporter, int mergeCount,
			MergeStratege strategy)
	{
		this.targetReporter = targetReporter;
		this.mergeCount = mergeCount;
		if (strategy != null)
		{
			this.stratege = strategy;
		}
	}

	public MergeResultReporter(ResultReporter targetReporter, String strategy)
	{
		this.targetReporter = targetReporter;

		if ("min".equalsIgnoreCase(strategy))
		{
			this.stratege = MergeStratege.MIN;
		} else if ("max".equalsIgnoreCase(strategy))
		{
			this.stratege = MergeStratege.MAX;
		}
	}

	public MergeResultReporter(ResultReporter targetReporter, int mergeCount,
			String strategy)
	{
		this.targetReporter = targetReporter;
		this.mergeCount = mergeCount;

		if ("min".equalsIgnoreCase(strategy))
		{
			this.stratege = MergeStratege.MIN;
		} else if ("max".equalsIgnoreCase(strategy))
		{
			this.stratege = MergeStratege.MAX;
		}
	}

	/* (non-Javadoc)
	 * @see blackstar.agent.monitor.reporter.ResultReporter#report(blackstar.agent.monitor.reporter.ReportData)
	 */
	public synchronized void report(ReportData data)
	{
		this.datas.add(data.getData());
		if (this.datas.size() >= this.mergeCount)
		{
			long resultData = 0;
			switch (this.stratege)
			{
			case MIN:
				resultData = Collections.min(this.datas);
				break;
			case MAX:
				resultData = Collections.max(this.datas);
				break;
			case AVARAGE:
			default:
				for (Long d : this.datas)
				{
					resultData += d;
				}
				resultData = (long) Math.ceil((double) resultData
						/ this.datas.size());
				break;
			}

			this.targetReporter.report(new ReportData(data.getJvmid(), data
					.getId(), resultData, data.getTimestamp()));

			this.datas.clear();
		}
	}
}
